/*
 * Copyright 2008,2009,2010 Daniel Freitas
 * 
 * This file is part of DMF Generic DAO.
 * 
 * DMF Generic DAO is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General
 * Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
 * later version.
 * 
 * DMF Generic DAO is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU Lesser General Public License along with DMF Generic DAO. If not, see
 * <http://www.gnu.org/licenses/>.
 */
package com.googlecode.dmf.genericdao.util;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import com.googlecode.dmf.genericdao.GenericDao;

/**
 * A utility class for reflection operations. Exposes some common, otherwise static, methods as instance methods to
 * allow for easier testability.
 * 
 * @author <a href="mailto:daniel.mfreitas@gmail.com">Daniel Freitas</a>
 * 
 */
public class BaseReflectioner implements Reflectioner {

    /**
     * 
     * {@inheritDoc}
     * 
     * @see com.googlecode.dmf.genericdao.util.Reflectioner#getMethodByName(java.lang.Class, java.lang.String,
     *      java.lang.Class<?>[])
     */
    public Method getMethodByName(final Class<?> clazz, final String methodName, final Class<?>... parameterTypes)
            throws SecurityException, NoSuchMethodException {
        return clazz.getMethod(methodName, parameterTypes);
    }

    /**
     * 
     * {@inheritDoc}
     * 
     * @see com.googlecode.dmf.genericdao.util.Reflectioner#getDaoEntityClass(java.lang.Class)
     */
    public Class<?> getDaoEntityClass(final Class<?> clazz) {
        Class<?> entityClass = null;
        Type[] implementedInterfaces = clazz.getGenericInterfaces();

        for (Type type : implementedInterfaces) {
            if (type instanceof ParameterizedType) {
                ParameterizedType parameterizedType = (ParameterizedType) type;
                Type rawType = parameterizedType.getRawType();

                Class<?> rawClass = (Class<?>) rawType;

                if (GenericDao.class.isAssignableFrom(rawClass)) {
                    entityClass = (Class<?>) (parameterizedType).getActualTypeArguments()[0];
                    return entityClass;
                }
            } else {
                entityClass = getDaoEntityClass((Class<?>) type);

                if (entityClass != null) {
                    return entityClass;
                }
            }
        }

        return null;
    }
}
